
#include <boost/algorithm/string.hpp>
#include "PackageFactory.h"

#include "Response.h"
#include "DebugStream.h"

namespace Engine {

PackageRef CPackageFactory::Parse(boost::asio::streambuf& data, CRequestAllocator* allocator)
{
	PackageRef p;

	istream is(&data);
	string line;
	
	// Head
	getline(is, line, '\n');
	boost::algorithm::trim(line);
	int pos = line.find(PROTOCOL_TAG);
	if(pos == 0) {
		DebugStream.writeCurrentTime();
		DebugStream << " Response received : " << line << '\n';
		p = PackageRef(new CResponse(line, data));
		DebugStream << '\n';
	}
	else
	if(pos > 0) {
		DebugStream.writeCurrentTime();
		DebugStream << " Request received : " << line << '\n';
		string cmd = line.substr(0, pos);
		boost::algorithm::trim(cmd);
		if(allocator) {
			p = allocator->alloc(cmd, data);
		}
		
		if(!p) {
			DebugStream << "Unknown command : " << cmd << "\n";
			throw CPackageParseException() << parse_error("Unknown command : " + cmd);
		}
		DebugStream << '\n';
	}
	else {
		DebugStream << "Invalie Package Data: \n";
		DebugStream << line << '\n';
		char ch;
		while(is.get(ch)) DebugStream << ch;
		DebugStream << '\n';
	}

	return p;
}

#define MAX_LINE_SIZE 256

PackageRef CPackageFactory::Parse(boost::shared_ptr<std::istream> is, CRequestAllocator* allocator)
{
	PackageRef p;
	string line;
	line.reserve(MAX_LINE_SIZE);

	while(!p) {
		// Head
		//getline(*is, line, '\n');

		char ch[1];
		while(1) {
			is->read(ch, 1);
			if(is->fail() || is->eof()) throw std::exception("End of stream");
			//DebugStream << "CPackageFactory::Parse - read ch : " << ch[0] << '\n';
			if(ch[0] == '\n') break;
			line.push_back(ch[0]);
		}
		line.push_back('\0');
		boost::algorithm::trim(line);
		int pos = line.find(PROTOCOL_TAG);
		if(pos < 0) continue;

		try {
			if(pos == 0) {
				DebugStream << "Stream response received : " << line << '\n';
				p = PackageRef(new CResponse(line, is));
				DebugStream << '\n';
			}
			else 
			if(pos > 0) {
				DebugStream << "Stream request received : " << line << '\n';
				string cmd = line.substr(0, pos);
				boost::algorithm::trim(cmd);

				if(allocator) {
					p = allocator->alloc(cmd, is);
				}
				
				if(!p) {
					DebugStream << "Stream unknown command : " << cmd << "\n";
				}
				DebugStream << '\n';
			}
		}
		catch(CPackageParseException&) {
		}
		
	}

	return p;
}

}